using System.Collections.Generic;
using System.Linq;

namespace WenYu.Core.Errors
{
    /// <summary>
    /// CodeGen 错误提供者 - 提供代码生成阶段错误的便捷构建方法
    /// </summary>
    public static class CodeGenErrors
    {
        /// <summary>
        /// E001: 变量未定义
        /// </summary>
        public static CompileError UndefinedVariable(
            string varName, 
            int line, 
            int column, 
            string sourceCode, 
            List<string> availableVariables = null,
            string filePath = "")
        {
            var builder = ErrorBuilder.Create("E001", $"变量 \"{varName}\" 未定义")
                .AtPosition(line, column)
                .InFile(filePath)
                .WithSource(sourceCode)
                .WithExplanation($"在使用变量 \"{varName}\" 之前，需要先声明它。就像要用一个盒子，得先准备好这个盒子。")
                .AddSuggestion($"在第{line}行之前声明变量：整型 {varName} 是 0。")
                .AddSuggestion($"或者从输入获取：整型 {varName} 是 输入（）。")
                .AddSuggestion("检查是否有拼写错误（注意同音字）")
                .AddKnowledgeWithDocUrl("查看【02-数据类型与变量】学习变量声明")
                .AddHelp("变量必须\"先声明，后使用\"");
            
            // 如果有可用变量列表，添加到提示中
            if (availableVariables != null && availableVariables.Count > 0)
            {
                builder.AddContext("availableVariables", availableVariables);
                
                // 查找相似的变量名
                var similar = FindSimilarVariables(varName, availableVariables);
                if (similar.Count > 0)
                {
                    builder.AddHelp($"你可能想找的变量：{string.Join("、", similar)}");
                }
                else
                {
                    builder.AddHelp($"当前已定义的变量：{string.Join("、", availableVariables)}");
                }
            }
            
            return builder.Build();
        }
        
        /// <summary>
        /// E002: 重复声明变量
        /// </summary>
        public static CompileError DuplicateVariable(
            string varName, 
            int line, 
            int column, 
            string sourceCode,
            int firstDefinedLine = 0,
            string filePath = "")
        {
            var builder = ErrorBuilder.Create("E002", $"变量 \"{varName}\" 重复声明")
                .AtPosition(line, column)
                .InFile(filePath)
                .WithSource(sourceCode)
                .WithExplanation($"变量 \"{varName}\" 已经在前面声明过了，不能重复声明。");
            
            if (firstDefinedLine > 0)
            {
                builder.AddSuggestion($"变量 \"{varName}\" 首次声明在第{firstDefinedLine}行");
            }
            
            builder.AddSuggestion("如果要修改变量的值，直接赋值即可，不需要再次声明")
                .AddSuggestion($"正确写法：{varName} 是 新值。（注意：没有类型关键字）")
                .AddSuggestion("如果确实需要另一个变量，请使用不同的名字")
                .AddKnowledgeWithDocUrl("查看【02-数据类型与变量】了解变量声明和赋值的区别")
                .AddHelp("提示：声明变量用 '整型 甲 是 10。'，修改变量用 '甲 是 20。'");
            
            return builder.Build();
        }
        
        /// <summary>
        /// E003: 类型不匹配
        /// </summary>
        public static CompileError TypeMismatch(
            string expected, 
            string actual, 
            int line, 
            int column, 
            string sourceCode,
            string varName = "",
            string filePath = "")
        {
            var varInfo = string.IsNullOrEmpty(varName) ? "" : $" \"{varName}\"";
            
            return ErrorBuilder.Create("E003", "类型不匹配")
                .AtPosition(line, column)
                .InFile(filePath)
                .WithSource(sourceCode)
                .WithExplanation($"变量{varInfo}被声明为{expected}类型，只能存储{GetTypeDescription(expected)}。但这里提供的是{actual}类型。")
                .AddSuggestion(GetTypeConversionSuggestion(expected, actual))
                .AddSuggestion($"如果要存储{GetTypeDescription(actual)}，应该声明为：{actual}{varInfo} 是 ...")
                .AddKnowledgeWithDocUrl("查看【02-数据类型与变量】了解类型系统")
                .AddKnowledge($"{expected}类型：{GetTypeExamples(expected)}")
                .AddKnowledge($"{actual}类型：{GetTypeExamples(actual)}")
                .AddHelp($"学习提示：想象{expected}类型变量是一个\"{GetTypeDescription(expected)}盒子\"，只能装{GetTypeDescription(expected)}。")
                .Build();
        }
        
        /// <summary>
        /// E004: 函数未定义
        /// </summary>
        public static CompileError UndefinedFunction(
            string funcName, 
            int line, 
            int column, 
            string sourceCode,
            List<string> availableFunctions = null,
            string filePath = "")
        {
            var builder = ErrorBuilder.Create("E004", $"函数 \"{funcName}\" 未定义")
                .AtPosition(line, column)
                .InFile(filePath)
                .WithSource(sourceCode)
                .WithExplanation($"在调用函数 \"{funcName}\" 之前，需要先定义它。")
                .AddSuggestion("检查函数名是否拼写正确")
                .AddSuggestion("确保函数定义在调用之前")
                .AddSuggestion("如果是标准库函数，查看文档确认函数名")
                .AddKnowledgeWithDocUrl("查看【05-函数】学习函数定义")
                .AddKnowledgeWithUrl("查看【09-标准库函数】查找内置函数", 
                    ErrorDocumentationConfig.GetStandardLibUrl())
                .AddHelp("提示：函数定义格式 - [参数] 求 [返回类型] 之 法 [函数名] { ... }");
            
            // 如果有可用函数列表，添加相似函数提示
            if (availableFunctions != null && availableFunctions.Count > 0)
            {
                var similar = FindSimilarVariables(funcName, availableFunctions);
                if (similar.Count > 0)
                {
                    builder.AddHelp($"你可能想找的函数：{string.Join("、", similar)}");
                }
            }
            
            return builder.Build();
        }
        
        /// <summary>
        /// E005: 参数数量不匹配
        /// </summary>
        public static CompileError ArgumentCountMismatch(
            string funcName,
            int expected,
            int actual,
            int line,
            int column,
            string sourceCode,
            string filePath = "")
        {
            return ErrorBuilder.Create("E005", "参数数量不匹配")
                .AtPosition(line, column)
                .InFile(filePath)
                .WithSource(sourceCode)
                .WithExplanation($"函数 \"{funcName}\" 需要 {expected} 个参数，但调用时提供了 {actual} 个参数。")
                .AddSuggestion($"检查函数定义，确认需要多少个参数")
                .AddSuggestion(expected > actual ? 
                    $"缺少 {expected - actual} 个参数" : 
                    $"多了 {actual - expected} 个参数")
                .AddKnowledgeWithDocUrl("查看【05-函数】了解函数调用")
                .AddHelp("提示：参数数量必须与函数定义时一致")
                .Build();
        }
        
        // ========== 私有辅助方法 ==========
        
        /// <summary>
        /// 查找相似的变量/函数名（简单的编辑距离算法）
        /// </summary>
        private static List<string> FindSimilarVariables(string target, List<string> candidates)
        {
            if (candidates == null || candidates.Count == 0)
                return new List<string>();
            
            // 简单实现：查找包含相同字符的变量
            var similar = candidates
                .Where(c => c.Length >= 2 && target.Length >= 2 && 
                       (c.Contains(target[0]) || target.Contains(c[0])))
                .Take(3)
                .ToList();
            
            return similar;
        }
        
        /// <summary>
        /// 获取类型描述
        /// </summary>
        private static string GetTypeDescription(string type)
        {
            return type switch
            {
                "整型" => "整数",
                "实型" => "小数",
                "文字" => "文本",
                "真假" => "真/假值",
                _ => type
            };
        }
        
        /// <summary>
        /// 获取类型示例
        /// </summary>
        private static string GetTypeExamples(string type)
        {
            return type switch
            {
                "整型" => "如 10、-5、0",
                "实型" => "如 3.14、-2.5、0.0",
                "文字" => "如 \"你好\"、\"18\"",
                "真假" => "如 真真、假假",
                _ => ""
            };
        }
        
        /// <summary>
        /// 获取类型转换建议
        /// </summary>
        private static string GetTypeConversionSuggestion(string expected, string actual)
        {
            if (expected == "整型" && actual == "文字")
                return "如果要存储数字，应该写：整型 变量 是 18。（不要用引号）";
            
            if (expected == "文字" && actual == "整型")
                return "如果要转换，使用：变量 是 数字 的 文字。";
            
            if (expected == "整型" && actual == "实型")
                return "如果要转换，使用：变量 是 转整型（实数）。";
            
            return $"如果要转换类型，查看【09-标准库函数】了解类型转换函数";
        }
    }
}

